/* main.cpp */

#include "CUnknown.h"
#include "main.h"

int main(int argc, char* argv[]) {

   int ret = 0;
   
   DWORD id = 0;
   wchar_t wszFilename[ _MAX_PATH ];
   
   HRESULT hr;        
   
   CComPtr<IDiaDataSource> pSource;
   CComPtr<IDiaSession> pSession;
   CComPtr<IDiaSymbol> pGlobal;   
   CComPtr<IDiaEnumTables> pTables;
   
   CUnknown* ptr = getCUnknown();
  
   if ( argc < 2 ) {
   
      Fatal("Usage: readpdb <filename.pdb>");
   }
    
   mbstowcs( wszFilename, argv[1], sizeof( wszFilename )/sizeof( wszFilename[0] ) );
	  
   hr = CoInitialize(NULL);
         
   if ( FAILED(hr) ) {
   
      Fatal("CoInitialize failed\n");
   }
    
   /* Acquire a data source by creating an IDiaDataSource interface */	
   hr = CoCreateInstance( CLSID_DiaSource, NULL, CLSCTX_INPROC_SERVER, __uuidof( IDiaDataSource ), (LPVOID *)&pSource);
   
   if ( FAILED(hr) ) {
			
      Fatal("Could not CoCreate CLSID_DiaSource. Register msdiaxxx.dll.");
   }
   
   /* Call IDiaDataSource::loadDataFromPdb or IDiaDataSource::loadDataForExe to load the debugging information */
   if ( FAILED( pSource->loadDataFromPdb( wszFilename ) ) ) {
   
      if ( FAILED( pSource->loadDataForExe( wszFilename, NULL, NULL ) ) ) {
	  
         Fatal( "loadDataFromPdb/Exe, FAILED" );
      }
   }
   
   /* Call IDiaDataSource::openSession to open an IDiaSession to gain access to the debugging information */
   if ( FAILED( pSource->openSession( &pSession ) ) ) {
   
      Fatal( "openSession, FAILED" );
   }
  
   /* Use the methods in IDiaSession to query for the symbols in the data source */  
   if ( FAILED( pSession->get_globalScope( &pGlobal) ) ) {
   
        Fatal( "get_globalScope, FAILED" );
   }
   
   if ( FAILED( pSession->getEnumTables( &pTables ) ) ) {
   
      Fatal( "getEnumTables, FAILED" );
   }
      
   /* Retrieves the unique symbol identifier */     
   if ( FAILED(pGlobal->get_symIndexId( &id ))   ) {
   
      Fatal("IDiaSymbol::get_symIndexId(), Failed(property is not available for the symbol)");
   }
            
   /* Finally */   
   if ( argc > 2 ) {
   
      parse(pSource, pSession, pGlobal, pTables, argc - 2, (const char**)(argv + 2));	  
   } else {
      
      parse(pSource, pSession, pGlobal, pTables);
   }
   
   /*  Following few assignments are mandatory or else, be ready to get lot of Access Violation exceptions(~CComPtr()) */   
   pSource = NULL; 
   pSession = NULL; 
   pGlobal = NULL;
   pTables = NULL;   
  
   CoUninitialize();
      
   return ret;
}